﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Data.SQLite;
using Zimmerreservierung.Controller;
using Zimmerreservierung.Model;
using System.Collections.Generic;

namespace Tests
{
    [TestClass]
    public class UnitTestReservierung
    {
        public TestContext TestContext { get; set; }
        private static KundenController kController;
        private static ZimmerController zController;
        private static ReservierungsController rController;
        
        [ClassInitialize()]
        public static void ClassInitialize(TestContext context)
        {
            using (SQLiteConnection connection = new SQLiteConnection("Data Source=testdb.dat"))
            {
                connection.Open();
                using (SQLiteCommand command = new SQLiteCommand(connection))
                {
                    command.CommandText = "DROP TABLE IF EXISTS Kunde";
                    command.ExecuteNonQuery();
                    command.CommandText = "DROP TABLE IF EXISTS Zimmer";
                    command.ExecuteNonQuery();
                    command.CommandText = "DROP TABLE IF EXISTS Reservierung";
                    command.ExecuteNonQuery();

                    command.CommandText = "CREATE TABLE IF NOT EXISTS Kunde ( ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, Name VARCHAR(100) NOT NULL, Rechnungsaddresse VARCHAR(100) NOT NULL, "
                                                                            + " Firmenname VARCHAR(100),  Rabatt REAL, Telefonnummer VARCHAR(100) NOT NULL, Faxnummer VARCHAR(100), Email VARCHAR(100), "
                                                                            + " Web VARCHAR(100), Notiz TEXT );";
                    command.ExecuteNonQuery();

                    command.CommandText = "CREATE TABLE IF NOT EXISTS Zimmer ( ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, Name VARCHAR(100) NOT NULL, MaxBelegzahl INTEGER NOT NULL, "
                                                                            + " PreisEZ REAL NOT NULL, PreisDZ REAL, PreisDreifachZ REAL, PreisEZmitKind REAL, PreisEZmit2Kind REAL, PreisDZmitKind REAL );";
                    command.ExecuteNonQuery();

                    command.CommandText = "CREATE TABLE IF NOT EXISTS Reservierung (" +
                        "ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " +
                        "KundenId INTEGER NOT NULL, " +
                        "ZimmerId INTEGER NOT NULL, " +
                        "RechnungsId INTEGER, " +
                        "Rabatt REAL, " +
                        "Zimmerpreis REAL NOT NULL, " +
                        "Zimmerpreisart VARCHAR(10) NOT NULL, " +
                        "Storniert INTEGER, " +
                        "Startdatum DATETIME NOT NULL, " +
                        "Enddatum DATETIME NOT NULL, " +
                        "FruehzeitigesEnddatum DATETIME, " +
                        "FOREIGN KEY(KundenId) REFERENCES Kunde(ID), " +
                        "FOREIGN KEY(ZimmerId) REFERENCES Zimmer(ID), " +
                        "FOREIGN KEY(RechnungsId) REFERENCES Rechnung(ID) );";
                    command.ExecuteNonQuery();
                }
                connection.Close();
            }

            kController = KundenController.getInstance();
            kController.startConnection("Data Source=testdb.dat");

            zController = ZimmerController.getInstance();
            zController.startConnection("Data Source=testdb.dat");

            rController = ReservierungsController.getInstance();
            rController.startConnection("Data Source=testdb.dat");
        }

        [TestMethod]
        public void testAddReservierung()
        {
            try
            {
                bool ok = kController.StoreKunde("Kunde 1", "TestRA 153, 1010 Wien", "testFN", "0.20", "+436991546513854", "+436991546513854", "test@test.at", "http://test.at", "testNotiz");
                Assert.AreEqual(true, ok);

                ok = kController.StoreKunde("Kunde 2", "TestRA 153, 1010 Wien1", "testFN1", "0.10", "+4369915465138541", "+4369915465138541", "test@test1.at", "http://test1.at", "testNotiz1");
                Assert.AreEqual(true, ok);

                ok = zController.StoreZimmer("Zimmer 1", 3, 10.0, 20.0, 30.0, 20.0, 30.0, 40.0);
                Assert.AreEqual(true, ok);

                ok = zController.StoreZimmer("Zimmer 2", 3, 20.0, 30.0, 40.0, 30.0, 40.0, 50.0);
                Assert.AreEqual(true, ok);

                DateTime startdatum = new DateTime(2013, 10, 1, 14, 0, 0);
                DateTime enddatum = new DateTime(2013, 10, 15, 5, 0, 0);

                double kosten = rController.CalculateKosten(startdatum, enddatum, 20, 10.0, 20);
                string zimmerkosten = Convert.ToString(kosten);

                ok = rController.StoreReservierung(1, 1, "0.20", zimmerkosten, "1 EW", startdatum.ToString("yyyy-MM-dd HH:mm:ss.fff"), enddatum.ToString("yyyy-MM-dd HH:mm:ss.fff"));
                Assert.AreEqual(true, ok);

                startdatum = new DateTime(2013, 11, 1, 14, 0, 0);
                enddatum = new DateTime(2013, 11, 5, 10, 0, 0);
                kosten = rController.CalculateKosten(startdatum, enddatum, 20, 40, 20);
                zimmerkosten = Convert.ToString(kosten);

                ok = rController.StoreReservierung(1, 2, "0.20", zimmerkosten, "3 EW", startdatum.ToString("yyyy-MM-dd HH:mm:ss.fff"), enddatum.ToString("yyyy-MM-dd HH:mm:ss.fff"));
                Assert.AreEqual(true, ok);

                startdatum = new DateTime(2013, 11, 1, 14, 0, 0);
                enddatum = new DateTime(2013, 11, 5, 10, 0, 0);
                kosten = rController.CalculateKosten(startdatum, enddatum, 5, 10.0, 20);
                zimmerkosten = Convert.ToString(kosten);

                ok = rController.StoreReservierung(2, 1, "0.20", zimmerkosten, "1 EW", startdatum.ToString("yyyy-MM-dd HH:mm:ss.fff"), enddatum.ToString("yyyy-MM-dd HH:mm:ss.fff"));
                Assert.AreEqual(true, ok);

                startdatum = new DateTime(2013, 12, 1, 14, 0, 0);
                enddatum = new DateTime(2013, 12, 5, 10, 0, 0);
                kosten = rController.CalculateKosten(startdatum, enddatum, 5, 20.0, 20);
                zimmerkosten = Convert.ToString(kosten);

                ok = rController.StoreReservierung(2, 2, "0.20", zimmerkosten, "2 EW", startdatum.ToString("yyyy-MM-dd HH:mm:ss.fff"), enddatum.ToString("yyyy-MM-dd HH:mm:ss.fff"));
                Assert.AreEqual(true, ok);
            }
            catch (Exception ex)
            {
                Assert.Fail(ex.Message);
            }
        }

        [TestMethod]
        public void testGetReservierung(int id, bool storniert)
        {
            try
            {
                Reservierung reservierung = rController.GetReservierung(1, false);
                Kunde kunde = kController.GetKunde(1);
                Zimmer zimmer = zController.GetZimmer(1);

                Assert.IsNotNull(reservierung);
                Assert.AreEqual("Kunde 1", reservierung.KundeName);
                Assert.AreEqual(kunde.Name, reservierung.Kunde.Name);
                Assert.AreEqual(zimmer.Name, reservierung.Zimmer.Name);
                Assert.AreEqual(100, reservierung.Zimmerpreis);
                Assert.AreEqual(20, reservierung.Rabatt);
                Assert.IsFalse(reservierung.Storniert);
            }
            catch (Exception ex)
            {
                Assert.Fail(ex.Message);
            }
        }

        [TestMethod]
        public void testGetReservierungen()
        {
            try
            {
                List<Reservierung> reservierungen = rController.GetReservierungen(false);

                Assert.AreEqual(4, reservierungen.Count);
                Assert.AreEqual("Kunde 1", reservierungen[0].KundeName);
                Assert.AreEqual("Zimmer 1", reservierungen[0].Zimmer.Name);
                Assert.AreEqual("Kunde 2", reservierungen[3].KundeName);
                Assert.AreEqual("Zimmer 2", reservierungen[3].Zimmer.Name);
            }
            catch (Exception ex)
            {
                Assert.Fail(ex.Message);
            }
        }

        [TestMethod]
        public void testGetFreieZimmer()
        {
            try
            {
               DateTime startdatum = new DateTime(2013, 11, 1, 14, 0, 0);
               DateTime enddatum = new DateTime(2013, 11, 5, 10, 0, 0);

               List<Zimmer> freieZimmer = rController.GetFreieZimmer(startdatum.ToString("yyyy-MM-dd HH:mm:ss.fff"), enddatum.ToString("yyyy-MM-dd HH:mm:ss.fff"));
               Assert.AreEqual(0, freieZimmer.Count);

               startdatum = new DateTime(2013, 10, 1, 14, 0, 0);
               enddatum = new DateTime(2013, 10, 15, 5, 0, 0);

               freieZimmer = rController.GetFreieZimmer(startdatum.ToString("yyyy-MM-dd HH:mm:ss.fff"), enddatum.ToString("yyyy-MM-dd HH:mm:ss.fff"));
               Assert.AreEqual(1, freieZimmer.Count);
            }
            catch (Exception ex)
            {
                Assert.Fail(ex.Message);
            }
        }

        [TestMethod]
        public void testStornieren()
        {
            try
            {
                bool ok = rController.Stornieren(1);
                Assert.AreEqual(true, ok);

                Reservierung r = rController.GetReservierung(1, true);
                Kunde kunde = kController.GetKunde(1);
                Zimmer zimmer = zController.GetZimmer(1);

                Assert.IsNotNull(r);
                Assert.AreEqual("Kunde 1", r.KundeName);
                Assert.AreEqual(kunde.Name, r.Kunde.Name);
                Assert.AreEqual(zimmer.Name, r.Zimmer.Name);
                Assert.IsTrue(r.Storniert);

                List<Reservierung> reservierungen = rController.GetReservierungen(false);
                Assert.AreEqual(3, reservierungen.Count);

                List<Reservierung> stornierungen = rController.GetReservierungen(true);
                Assert.AreEqual(1, stornierungen.Count);
            }
            catch (Exception ex)
            {
                Assert.Fail(ex.Message);
            }
        }

        [TestMethod]
        public void testGetStornierunskosten(int id)
        {
            try
            {
                double kosten = rController.GetStornierungskosten(1);
                Reservierung r = rController.GetReservierung(1, true);

                Assert.AreEqual(100, kosten);
            }
            catch(Exception ex)
            {
                Assert.Fail(ex.Message);
            }
        }

        [TestMethod]
        public void testFruehzeitigeAbreise(int id, string fruehzeitigesEndDatum)
        {
            try
            {
                DateTime time = DateTime.Now;//.ToString("yyyy-MM-dd HH:mm:ss.fff");

                int ok = rController.FruehzeitigeAbreise(2, time);
                Assert.AreEqual(-1, ok);

                ok = rController.FruehzeitigeAbreise(2, time);
                Assert.AreEqual(-2, ok);

                ok = rController.FruehzeitigeAbreise(2, time);
                Assert.AreEqual(1, ok);

                Reservierung r = rController.GetReservierung(2, true);
                Assert.IsNotNull(r);

                Assert.AreEqual(time, r.FruehzeitigesEnddatum);
            }
            catch (Exception ex)
            {
                Assert.Fail(ex.Message);
            }
        }

        [TestMethod]
        public void testGetKosten(int id, int rabatt, double zimmerKosten)
        {
            DateTime startdatum = new DateTime(2013, 10, 1, 14, 0, 0);
            DateTime enddatum = new DateTime(2013, 10, 15, 5, 0, 0);

            double kosten = rController.CalculateKosten(startdatum, enddatum, 20, 10.0, 20);
            Assert.AreEqual(1, kosten);

            startdatum = new DateTime(2013, 11, 1, 14, 0, 0);
            enddatum = new DateTime(2013, 11, 20, 10, 0, 0);
            kosten = rController.CalculateKosten(startdatum, enddatum, 20, 10.0, 20);
            Assert.AreEqual(1, kosten);

            startdatum = new DateTime(2013, 12, 1, 14, 0, 0);
            enddatum = new DateTime(2013, 12, 2, 5, 0, 0);
            kosten = rController.CalculateKosten(startdatum, enddatum, 20, 10.0, 20);
            Assert.AreEqual(1, kosten);

            startdatum = new DateTime(2013, 1, 1, 14, 0, 0);
            enddatum = new DateTime(2013, 1, 15, 5, 0, 0);
            kosten = rController.CalculateKosten(startdatum, enddatum, 20, 10.0, 20);
            Assert.AreEqual(1, kosten);

            startdatum = new DateTime(2013, 2, 1, 14, 0, 0);
            enddatum = new DateTime(2013, 2, 8, 5, 0, 0);
            kosten = rController.CalculateKosten(startdatum, enddatum, 20, 10.0, 20);
        }

       
    }
}
